home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ObjectHe.cpp
-
- Contains: ObjectHeap class implementation
-
- Written by: Michael Burbidge
-
- Copyright: © 1993 - 1994 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <4> 8/17/94 jpa Minimal changes to keep it compiling
- against current MemoryHeap API.
- <3> 8/8/94 jpa OD_DEBUG --> ODDebug
- <2> 6/10/94 MB Make it build
- <1> 6/9/94 MB first checked in
- <2> 5/9/94 MB #1162181: Changes necessary to install MMM.
- <1> 4/29/94 MB first checked in
- To Do:
- */
-
- #ifndef _PLATFMEM_
- #include "PlatfMem.h"
- #endif
-
- #ifndef _OBJECTHE_
- #include "ObjectHe.h"
- #endif
-
-
- //========================================================================================
- // CLASS PrivChunkyBlock
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlock::PrivChunkyBlock
- //----------------------------------------------------------------------------------------
-
- PrivChunkyBlock::PrivChunkyBlock()
- {
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlock::PrivChunkyBlock
- //----------------------------------------------------------------------------------------
-
- PrivChunkyBlock::PrivChunkyBlock(unsigned int sizeIndex,
- unsigned int blockIndex)
- {
- SetSizeIndex(sizeIndex);
- SetBlockIndex(blockIndex);
- SetBlockType(kBlockTypeId);
- SetMagicNumber(kMagicNumber);
- fNext = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlock::GetChunk
- //----------------------------------------------------------------------------------------
-
- PrivChunk* PrivChunkyBlock::GetChunk(ODBlockSize blkSize)
- {
- PrivChunk *chk
- = (PrivChunk *) ((ODBytePtr) this - sizeof(ODPrivChunkHeader) - blkSize * GetBlockIndex());
- return chk;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlock::IsBusy
- //----------------------------------------------------------------------------------------
-
- Boolean PrivChunkyBlock::IsBusy(ODBlockSize blockSize)
- {
- return this->GetChunk(blockSize)->IsBlockBusy(GetBlockIndex());
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlock::SetBusy
- //----------------------------------------------------------------------------------------
-
- void PrivChunkyBlock::SetBusy(ODBlockSize blockSize, Boolean busy)
- {
- this->GetChunk(blockSize)->SetBlockBusy(GetBlockIndex(), busy);
- }
-
-
- //========================================================================================
- // PrivChunk
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // PrivChunk::PrivChunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunk::PrivChunk(short blocksPerChunk,
- unsigned int sizeIndex,
- ODBlockSize blockSize)
- {
- fHeader.fBlockBusyBits = 0;
- void* blkPtr = (void *) ((ODBytePtr) this + sizeof(ODPrivChunkHeader));
- for (unsigned int i = 0; i < blocksPerChunk; i++)
- {
- PrivChunkyBlock *blk = new(blkPtr)PrivChunkyBlock(sizeIndex, i);
- blkPtr = (void *) ((ODBytePtr) blkPtr + blockSize);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunk::IsBlockBusy
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean PrivChunk::IsBlockBusy(unsigned int whichBlock)
- {
- unsigned short mask = 0x0001;
-
- for (short i = 0; i < whichBlock; i++)
- mask = mask << 1;
-
- return (fHeader.fBlockBusyBits & mask) != 0;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunk::SetBlockBusy
- //----------------------------------------------------------------------------------------
-
- void PrivChunk::SetBlockBusy(unsigned int whichBlock, Boolean busy)
- {
- unsigned short mask = 0x0001;
-
- for (short i = 0; i < whichBlock; i++)
- mask = mask << 1;
-
- if (busy)
- fHeader.fBlockBusyBits |= mask;
- else
- fHeader.fBlockBusyBits &= ~mask;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunk::GetBlock
- //----------------------------------------------------------------------------------------
-
- PrivChunkyBlock* PrivChunk::GetBlock(unsigned int blkIndex, ODBlockSize blkSize)
- {
- PrivChunkyBlock * blk
- = (PrivChunkyBlock *) ((ODBytePtr) this + sizeof(ODPrivChunkHeader) + blkIndex * blkSize);
- return blk;
- }
-
-
- //========================================================================================
- // ObjectHeap
- //========================================================================================
-
- const ODBlockSize ObjectHeap_kDefaultBlockSizes[]
- = { (ODBlockSize) sizeof(PrivChunkyBlock), 10, 14, 18, 0 };
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::ObjectHeap(unsigned long initialSize,
- unsigned long incrementSize,
- unsigned long hugeBlockSize,
- Boolean fromSysMemory,
- short blocksPerChunk) :
- BestFitHeap(initialSize, incrementSize, hugeBlockSize, fromSysMemory),
- fBlockSizes(ObjectHeap_kDefaultBlockSizes)
- {
- #if ODDebug
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::ObjectHeap(const ODBlockSize* blockSizes,
- unsigned long initialSize,
- unsigned long incrementSize,
- unsigned long hugeBlockSize,
- Boolean fromSysMemory,
- short blocksPerChunk) :
- BestFitHeap(initialSize, incrementSize, hugeBlockSize, fromSysMemory),
- fBlockSizes(blockSizes)
- {
- #if ODDebug
- CompilerCheck();
- #endif
-
- fBlocksPerChunk = blocksPerChunk;
-
- for (fNumberOfBlockSizes = 0; fBlockSizes[fNumberOfBlockSizes]; fNumberOfBlockSizes++)
- ;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::IObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::IObjectHeap()
- {
- this->IBestFitHeap();
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::~ObjectHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ObjectHeap::~ObjectHeap()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoAllocate
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void* ObjectHeap::DoAllocate(ODBlockSize size, ODBlockSize& allocatedSize)
- {
- if (size + PrivChunkyBlock::kBusyOverhead > fBlockSizes[fNumberOfBlockSizes - 1])
- return BestFitHeap::DoAllocate(size, allocatedSize);
- else
- {
- unsigned int sizeIndex = this->SizeIndex(size);
- allocatedSize = fBlockSizes[sizeIndex] - PrivChunkyBlock::kBusyOverhead;
- return this->AllocateBlock(sizeIndex);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoBlockSize
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- ODBlockSize ObjectHeap::DoBlockSize(const void* ptr) const
- {
- PrivChunkyBlock *block
- = (PrivChunkyBlock *) ((ODBytePtr) ptr - PrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == PrivBestFitBlock::kBlockTypeId)
- return BestFitHeap::DoBlockSize(ptr);
- else
- return fBlockSizes[block->GetSizeIndex()] - PrivChunkyBlock::kBusyOverhead;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoFree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::DoFree(void* ptr)
- {
- PrivChunkyBlock *block
- = (PrivChunkyBlock *) ((ODBytePtr) ptr - PrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == PrivBestFitBlock::kBlockTypeId)
- BestFitHeap::DoFree(ptr);
- else
- this->FreeBlock(block);
- }
-
- #if ODDebug
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoIsValidBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean ObjectHeap::DoIsValidBlock(void* ptr) const
- {
- Boolean isBlockValid = false;
-
- PrivChunkyBlock *block
- = (PrivChunkyBlock *) ((ODBytePtr) ptr - PrivChunkyBlock::kBusyOverhead);
-
- if (block->GetBlockType() == PrivBestFitBlock::kBlockTypeId)
- isBlockValid = BestFitHeap::DoIsValidBlock(ptr);
- else
- isBlockValid
- = block->GetSizeIndex() <= fNumberOfBlockSizes &&
- block->GetBlockIndex() <= fBlocksPerChunk &&
- block->GetMagicNumber() == (unsigned int) PrivChunkyBlock::kMagicNumber;
-
- return isBlockValid;
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::DoReset
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::DoReset()
- {
- PrivChunkyBlockStack clr;
-
- for (int i = 0; i < fNumberOfBlockSizes; i++)
- fFreeLists[i] = clr;
-
- BestFitHeap::DoReset();
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::AllocateBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void *ObjectHeap::AllocateBlock(unsigned int sizeIndex)
- {
- if (fFreeLists[sizeIndex].Top() == NULL)
- this->CreateNewChunk(sizeIndex);
-
- PrivChunkyBlock * blk = fFreeLists[sizeIndex].Pop();
- if (blk != NULL)
- {
- blk->SetBusy(fBlockSizes[sizeIndex], true);
- return (void *) ((ODBytePtr) blk + PrivChunkyBlock::kBusyOverhead);
- }
- else
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::CreateNewChunk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::CreateNewChunk(unsigned int sizeIndex)
- {
- ODBlockSize allocatedSize;
- ODBlockSize allocSize = sizeof(ODPrivChunkHeader) + fBlocksPerChunk * fBlockSizes[sizeIndex];
- PrivChunk * chk = new(BestFitHeap::DoAllocate(allocSize, allocatedSize))PrivChunk(fBlocksPerChunk, sizeIndex, fBlockSizes[sizeIndex]);
- if (chk != NULL)
- {
- for (unsigned int i = 0; i < fBlocksPerChunk; i++)
- {
- PrivChunkyBlock * blk = chk->GetBlock(i, fBlockSizes[sizeIndex]);
- blk->SetBusy(fBlockSizes[sizeIndex], false);
- fFreeLists[sizeIndex].Push(blk);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::FreeBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::FreeBlock(PrivChunkyBlock* blk)
- {
- blk->SetBusy(fBlockSizes[blk->GetSizeIndex()], false);
- fFreeLists[blk->GetSizeIndex()].Push(blk);
-
- // Check to see if all blocks in this block's PrivChunk are free, if so then free the
- // PrivChunk.
-
- PrivChunk *chk = blk->GetChunk(fBlockSizes[blk->GetSizeIndex()]);
- if (!chk->IsBusy())
- {
- // Remove blocks in this PrivChunk from the free list. This is the achililles hill
- // of the Heap. Its difficult to remove blocks from a singly linked list
- // rapidly.
-
- void *begAddr = chk;
- void *endAddr = (void *) ((ODBytePtr) chk +
- sizeof(ODPrivChunkHeader) +
- fBlocksPerChunk * fBlockSizes[chk->GetSizeIndex()]);
- fFreeLists[chk->GetSizeIndex()].RemoveRange(begAddr, endAddr);
- BestFitHeap::DoFree(chk);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ObjectHeap::SizeIndex
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- unsigned int ObjectHeap::SizeIndex(ODBlockSize size)
- {
- for (unsigned int i = 0; i < fNumberOfBlockSizes; i++)
- if (size + PrivChunkyBlock::kBusyOverhead <= fBlockSizes[i])
- return i;
-
- // Uh oh! An internal error:
-
- PLATFORM_DEBUGGER_STRING("Internal error in ObjectHeap::SizeIndex");
-
- return 0xFFFFFFFF; // the former way of handling the internal error
- // we leave it in to defeat an xlC warning
- }
-
- #if ODDebug
- //----------------------------------------------------------------------------------------
- // ObjectHeap::CompilerCheck
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void ObjectHeap::CompilerCheck()
- {
- BestFitHeap::CompilerCheck();
-
- PrivChunkyBlock block;
-
- block.SetSizeIndex(0xF);
- block.SetBlockIndex(0xE);
- block.SetBlockType(PrivChunkyBlock::kBlockTypeId);
- block.SetMagicNumber(0xC);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0xF);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0xE);
- PLATFORM_ASSERT(block.GetBlockType() == PrivChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != PrivBestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0xC);
-
- block.SetSizeIndex(0x7);
- block.SetBlockIndex(0x6);
- block.SetBlockType(PrivBestFitBlock::kBlockTypeId);
- block.SetMagicNumber(0x4);
-
- PLATFORM_ASSERT(block.GetSizeIndex() == 0x7);
- PLATFORM_ASSERT(block.GetBlockIndex() == 0x6);
- PLATFORM_ASSERT(block.GetBlockType() == PrivBestFitBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetBlockType() != PrivChunkyBlock::kBlockTypeId);
- PLATFORM_ASSERT(block.GetMagicNumber() == 0x4);
- }
- #endif
-
- //========================================================================================
- // PrivChunkyBlockStack
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::PrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlockStack::PrivChunkyBlockStack()
- {
- fHead.SetNext(NULL);
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::PrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlockStack::PrivChunkyBlockStack(const PrivChunkyBlockStack& blk) :
- fHead(blk.fHead)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::operator=
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlockStack& PrivChunkyBlockStack::operator=(const PrivChunkyBlockStack& blk)
- {
- fHead = blk.fHead;
- return *this;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::Pop
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlock* PrivChunkyBlockStack::Pop()
- {
- PrivChunkyBlock * blk = fHead.GetNext();
- fHead.SetNext(blk->GetNext());
- return blk;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::Push
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void PrivChunkyBlockStack::Push(PrivChunkyBlock* blk)
- {
- blk->SetNext(fHead.GetNext());
- fHead.SetNext(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::RemoveRange
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void PrivChunkyBlockStack::RemoveRange(void *begAddr, void *endAddr)
- {
- PrivChunkyBlock *prevBlk = &fHead;
- PrivChunkyBlock *curBlk = fHead.GetNext();
-
- while (curBlk != NULL)
- {
- void *curAddr = curBlk;
-
- if (curAddr >= begAddr && curAddr <= endAddr)
- {
- prevBlk->SetNext(curBlk->GetNext());
- curBlk = curBlk->GetNext();
- }
- else
- {
- prevBlk = curBlk;
- curBlk = curBlk->GetNext();
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::Top
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlock* PrivChunkyBlockStack::Top()
- {
- return fHead.GetNext();
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::~PrivChunkyBlockStack
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- PrivChunkyBlockStack::~PrivChunkyBlockStack()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::operator new
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void *PrivChunkyBlockStack::operator new(size_t)
- {
- PLATFORM_DEBUGGER_STRING("\pPrivChunkyBlockStack should not be dynamically allocated");
- return NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // PrivChunkyBlockStack::operator delete
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void PrivChunkyBlockStack::operator delete(void *)
- {
- PLATFORM_DEBUGGER_STRING("\pPrivChunkyBlockStack should not be dynamically allocated");
- }
-
-